package com.wchen.project.ticket.service;

import com.alibaba.fastjson.JSON;
import com.wchen.project.common.constant.Constant;
import com.wchen.project.common.utils.SendMailUtil;
import com.wchen.project.common.utils.SslUtils;
import com.wchen.project.ticket.vo.EmailVO;
import com.wchen.project.ticket.vo.ResultVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.GZIPInputStream;

/**
 * @Desc:
 * @author: cww
 * @DateTime: 2019/12/27 17:07
 */
@Service
public class TicketAsyncService implements ITicketAsyncService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Value("${app.date}")
    private String date_arr_config;
    private static String date_arr;
    @Value("${app.url}")
    private String url_arr_config;
    private static String url_arr;

    @Value("${app.cookie}")
    private String cookie;

    @Value("${app.train}")
    private String train_arr_config;
    private static String train_arr;
    /**
     * 线程数据，根据查询日志区分
     */
    private static Map<String, String> thread_map = new HashMap<>();
    private static List<String> trainList = new ArrayList<>();
    private static String start_time_str = "05:57";
    private static String end_time_str = "23:30";
    /**
     * 每日查票时间
     */
    private static Date startTime;
    private static Date endTime;
    /**
     * 查到车票一轮持续时间 默认 10 分钟
     */
    private static long send_cycle = 10 * 60 * 1000;
    /**
     * 查到车票一轮发送几次邮件 默认 5 次
     */
    private static int count_send =  5;

    @PostConstruct
    public void transport() {
        date_arr = this.date_arr_config;
        url_arr = this.url_arr_config;
        train_arr = this.train_arr_config;
        if (!StringUtils.isEmpty(date_arr) && !StringUtils.isEmpty(url_arr)) {
            List<String> dateList = Arrays.asList(date_arr.split(","));
            List<String> urlList = Arrays.asList(url_arr.split(","));
            for (int i = 0; i < dateList.size(); i++) {
                thread_map.put(dateList.get(i) + "_first_send_time", "0");
                thread_map.put(dateList.get(i) + "_current_count", "0");
                thread_map.put(dateList.get(i) + "_url", urlList.get(i));
                thread_map.put(dateList.get(i) + "_err", "0");
            }
        }
        try {
            SimpleDateFormat FORMAT_TIME_MIN =  new SimpleDateFormat("HH:mm");
            startTime =  FORMAT_TIME_MIN.parse(start_time_str);
            endTime =  FORMAT_TIME_MIN.parse(end_time_str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (!StringUtils.isEmpty(train_arr)) {
            trainList = Arrays.asList(train_arr.split(","));
        }

    }

    @Override
    @Async()
    public void getTicketAndSendMailByDay(String date) {
        String firstSendTime = date + "_first_send_time";
        String currentCount = date + "_current_count";
        int errCount = Integer.valueOf(thread_map.get(date + "_err"));
        try{
            //生成一个URL对象
            URL url = new URL(thread_map.get(date + "_url"));
            int responseCode;
            HttpURLConnection urlConnection = null;
            BufferedReader reader;
            Date min = new Date();
            //SimpleDateFormat 是线程不安全的
            SimpleDateFormat FORMAT_TIME_MIN =  new SimpleDateFormat("HH:mm");
            Date now = FORMAT_TIME_MIN.parse(FORMAT_TIME_MIN.format(min));
            //忽略Ssl(针对12306)
            SslUtils.ignoreSsl();
            try {
                /**
                 * 这是为了防止12306对同一ip多次访问进行限制
                 * 这里填的ip是暂时有效的，想要获取更多就得自己去找 搜索代理ip
                 */
                System.getProperties().setProperty("proxySet", "false");
                System.setProperty("http.proxyHost", "115.239.25.250");
                System.setProperty("http.proxyPort", "9999");
                //打开URL
                urlConnection = (HttpURLConnection) url.openConnection();
                //伪造一个请求头 一般网页不用，有些网站会看你有没有请求头，比如 12306......
                urlConnection.setRequestMethod("GET");
                urlConnection.setRequestProperty("Accept","*/*");
                urlConnection.setRequestProperty("Accept-Encoding","gzip, deflate, br");
                urlConnection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
                urlConnection.setRequestProperty("Cache-Control","no-cache");
                urlConnection.setRequestProperty("Connection","keep-alive");
                urlConnection.setRequestProperty("Content-Type","application/json;charset=UTF-8");
                urlConnection.setRequestProperty("If-Modified-Since","0");
                // 来自启动传参的cookie，方便改变参数，无需重新打包
                if (!StringUtils.isEmpty(Constant.cookie)) {
                    urlConnection.setRequestProperty("Cookie", Constant.cookie);
                } else {
                    urlConnection.setRequestProperty("Cookie", cookie);
                }
                urlConnection.setRequestProperty("Host","kyfw.12306.cn");
                urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36");
                urlConnection.setRequestProperty("X-Requested-With","XMLHttpRequest");
                urlConnection.setRequestProperty("Sec-Fetch-Site","same-origin");
                urlConnection.setRequestProperty("Sec-Fetch-Mode","cors");
            } catch (Exception e) {
                logger.error("Http 请求异常：",e);
                throw new Exception("Http 请求异常：");
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
            }
            //获取服务器响应代码
            responseCode = urlConnection.getResponseCode();
            logger.info("请求返回状态 responseCode："+responseCode);
            //假如响应代码为200，就是代表成功
            if(responseCode == 200){
                // 读取返回内容
                StringBuffer buffer = new StringBuffer();
//              BufferedReader builder1 = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(),"UTF-8"));
                InputStream stream = new GZIPInputStream(urlConnection.getInputStream());
                reader = new BufferedReader(new InputStreamReader(stream,"UTF-8"));
                String temp;
                while ((temp = reader.readLine()) != null) {
                    buffer.append(temp);
                    buffer.append("\n");
                }
//                    logger.info("请求返回原数据:" + buffer);
                if (!buffer.toString().isEmpty()) {
                    ResultVO resultVO ;
                    resultVO = JSON.parseObject(buffer.toString(), ResultVO.class);
                    boolean isSendEmail = false;
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append(date+ "<br>");
                    for (String resultStr:resultVO.getData().getResult()){
                        List<String> strings = Arrays.asList(resultStr.split("\\|"));
                        for (String train : trainList) {
                            if (train.equals(strings.get(3))){
//                            if ((!"无".equals(strings.get(26)))||(!"无".equals(strings.get(30)))||(!"无".equals(strings.get(31)))){
//                                if ((!"无".equals(strings.get(30)))||(!"无".equals(strings.get(31)))){
                                String secondCount = strings.get(30);
                                if ((!"无".equals(secondCount)) && (Integer.valueOf(secondCount) >=2)){
                                    String time = strings.get(8) + "-" + strings.get(9) + "   " + strings.get(10);
                                    stringBuilder.append(train + ": " + time + "<br>"+"无座："+strings.get(26)+"<br>"+"二等座："+strings.get(30)+"<br>"+"一等座："+strings.get(31)+"<br>");
                                    logger.info(train + " 刷到余票");
                                    logger.info(train + "： " + time);
                                    logger.info("无座："+strings.get(26));
                                    logger.info("二等座："+ secondCount);
                                    logger.info("一等座："+strings.get(31));
                                    isSendEmail = true;
                                }
                            }
                        }
                    }
                    if (now.before(endTime) && now.after(startTime)) {
                        logger.info(date + " 12306系统在开放时间区间内");
                    } else {
                        isSendEmail = false;
                        logger.info("12306系统不在开放时间区间内");
                    }
                    Date timestamp = new Date();
                    long currentFirstSendTime = Long.valueOf(thread_map.get(firstSendTime));
                    int currentCountTemp = Integer.valueOf(thread_map.get(currentCount));
                    long timeDifference = (timestamp.getTime() - currentFirstSendTime);
                    if (isSendEmail){
                        if ((currentCountTemp == 0 || timeDifference < send_cycle) && currentCountTemp < count_send) {
                            if (currentCountTemp == 0) {
                                timeDifference = 0;
                                thread_map.put(firstSendTime, Long.toString(timestamp.getTime()));
                            }
                            logger.info("刷到相关余票 时间："+ date);
                            EmailVO emailVO = new EmailVO();
                            emailVO.setEmailAddress("352543607@qq.com");
                            emailVO.setEmailSubject("刷到余票");
                            emailVO.setEmailContent(stringBuilder.toString());
                            SendMailUtil sendMailTest = new SendMailUtil();
                            sendMailTest.SendMail(emailVO);
//                                if ("2020-01-22".equals(date)) {
                                emailVO.setEmailAddress("294147287@qq.com");
                                sendMailTest.SendMail(emailVO);
//                                }
                            thread_map.put(currentCount,Integer.toString(++currentCountTemp));
                            logger.info(date + " 当前发送邮件次数：" + currentCountTemp);
                        } else {
                            logger.info("本次刷到相关余票但不发送邮件，距离下一轮发送时间: " + (send_cycle - timeDifference)/60000 + " 分钟" );
                        }
                    } else {
                        thread_map.put(currentCount,Integer.toString(0));
                        logger.info("本次未刷到相关余票 时间："+ date);
                    }
                    if (currentCountTemp > 0 && timeDifference >= send_cycle) {
                        thread_map.put(currentCount,Integer.toString(0));
                    }
                    //流程正常执行完成，复位异常计数器
                    thread_map.put(date + "_err", "0");
                }
            } else {
                logger.info("查询返回数据异常，服务器响应代码为"+ responseCode);
                throw new Exception("查询返回数据异常");
            }
        }catch(Exception e){
            e.printStackTrace();
            logger.info("查询异常 e:"+ e);
            if (errCount++ == 10) {
                EmailVO emailVO = new EmailVO();
                emailVO.setEmailAddress("294147287@qq.com");
                emailVO.setEmailSubject("查询服务异常提醒");
                emailVO.setEmailContent("查询服务异常提醒:" + e.getMessage());
                SendMailUtil sendMailTest = new SendMailUtil();
                try {
                    sendMailTest.SendMail(emailVO);
                    //异常提醒成功后复位异常计数器
                    thread_map.put(date + "_err", "0");
                } catch (Exception e1) {
                    logger.error("邮件发送失败！");
                }
            } else {
                thread_map.put(date + "_err", String.valueOf(errCount++));
            }
        }
    }

    @Override
    public void getMyOrderNoComplete(String url) throws Exception {
        //生成一个URL对象
        URL urlCon = new URL(url);
        int responseCode;
        HttpURLConnection urlConnection = null;
        BufferedReader reader;
        //忽略Ssl(针对12306)
        SslUtils.ignoreSsl();
        try {
            try {
                /**
                 * 这是为了防止12306对同一ip多次访问进行限制
                 * 这里填的ip是暂时有效的，想要获取更多就得自己去找 搜索代理ip
                 */
                System.getProperties().setProperty("proxySet", "false");
                System.setProperty("http.proxyHost", "115.239.25.250");
                System.setProperty("http.proxyPort", "9999");
                //打开URL
                urlConnection = (HttpURLConnection) urlCon.openConnection();
                //伪造一个请求头 一般网页不用，有些网站会看你有没有请求头，比如 12306......
                urlConnection.setRequestMethod("POST");
                urlConnection.setRequestProperty("Accept","application/json, text/javascript, */*; q=0.01");
                urlConnection.setRequestProperty("Accept-Encoding","gzip, deflate");
                urlConnection.setRequestProperty("Accept-Language","zh-CN");
                urlConnection.setRequestProperty("Cache-Control","no-cache");
                urlConnection.setRequestProperty("Connection","keep-alive");
                urlConnection.setRequestProperty("Content-Length","10");
                urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
                urlConnection.setRequestProperty("Cookie", cookie);
                // 来自启动传参的cookie，方便改变参数，无需重新打包
                if (!StringUtils.isEmpty(Constant.cookie)) {
                    urlConnection.setRequestProperty("Cookie", Constant.cookie);
                }
                urlConnection.setRequestProperty("Host","kyfw.12306.cn");
                urlConnection.setRequestProperty("Referer","https://kyfw.12306.cn/otn/view/train_order.html");
                urlConnection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko");
                urlConnection.setRequestProperty("X-Requested-With", "XMLHttpRequest");
                urlConnection.setDoOutput(true);
                urlConnection.setDoInput(true);
                urlConnection.setUseCaches(false);
                OutputStreamWriter osw = new OutputStreamWriter(urlConnection.getOutputStream(), "UTF-8");
                osw.write("");
                osw.flush();
                osw.close();
            } catch (Exception e) {
                logger.error("Http 请求异常：",e);
                throw new Exception("Http 请求异常：");
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
            }

            //获取服务器响应代码
            responseCode = urlConnection.getResponseCode();
            logger.info("请求返回状态 responseCode："+responseCode);
            // 读取返回内容
            StringBuffer buffer = new StringBuffer();
//            InputStream stream = new GZIPInputStream(urlConnection.getInputStream());
            reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(),"UTF-8"));
            String temp;
            while ((temp = reader.readLine()) != null) {
                buffer.append(temp);
                buffer.append("\n");
            }
//            logger.info("***************我的未完成订单请求结果**************:"  + buffer.toString().contains("{\"validateMessagesShowId\":\"_validatorMessage\",\"status\":true,\"httpstatus\":200,\"messages\":[],\"validateMessages\":{}}"));
            logger.info("***************请求结果**************:"  +
                    (buffer.toString().contains("{\"validateMessagesShowId\":\"_validatorMessage\",\"status\":true,\"httpstatus\":200,\"data\"") ||
                    buffer.toString().contains("{\"validateMessagesShowId\":\"_validatorMessage\",\"status\":true,\"httpstatus\":200,\"messages\":[],\"validateMessages\":{}}")));
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("未完成订单查询异常 e:"+ e);
        }
    }

    @Override
    public void getloginconf() throws Exception {
        //生成一个URL对象
        URL url = new URL("https://kyfw.12306.cn/otn/login/conf");
        int responseCode;
        HttpURLConnection urlConnection = null;
        BufferedReader reader;
        //忽略Ssl(针对12306)
        SslUtils.ignoreSsl();
        try {
            try {
                /**
                 * 这是为了防止12306对同一ip多次访问进行限制
                 * 这里填的ip是暂时有效的，想要获取更多就得自己去找 搜索代理ip
                 */
                System.getProperties().setProperty("proxySet", "false");
                System.setProperty("http.proxyHost", "115.239.25.250");
                System.setProperty("http.proxyPort", "9999");
                //打开URL
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestMethod("POST");
                urlConnection.setRequestProperty("Accept","*/*");
                urlConnection.setRequestProperty("Accept-Encoding","gzip, deflate, br");
                urlConnection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
                urlConnection.setRequestProperty("Connection","keep-alive");
                urlConnection.setRequestProperty("Content-Length","0");
                urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
                urlConnection.setRequestProperty("Cookie", cookie);
                // 来自启动传参的cookie，方便改变参数，无需重新打包
                if (!StringUtils.isEmpty(Constant.cookie)) {
                    urlConnection.setRequestProperty("Cookie", Constant.cookie);
                }
                urlConnection.setRequestProperty("Host","kyfw.12306.cn");
                urlConnection.setRequestProperty("Origin","https://kyfw.12306.cn");
                urlConnection.setRequestProperty("Referer","https://kyfw.12306.cn/otn/view/index.html");
                urlConnection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36");
                urlConnection.setRequestProperty("X-Requested-With", "XMLHttpRequest");
                urlConnection.setDoOutput(true);
                urlConnection.setDoInput(true);
                urlConnection.setUseCaches(false);
                OutputStreamWriter osw = new OutputStreamWriter(urlConnection.getOutputStream(), "UTF-8");
                osw.write("");
                osw.flush();
                osw.close();
            } catch (Exception e) {
                logger.error("Http 请求异常：",e);
                throw new Exception("Http 请求异常：");
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
            }

            //获取服务器响应代码
            responseCode = urlConnection.getResponseCode();
            logger.info("请求返回状态 responseCode："+responseCode);
            // 读取返回内容
            StringBuffer buffer = new StringBuffer();
//            InputStream stream = new GZIPInputStream(urlConnection.getInputStream());
            reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(),"UTF-8"));
            String temp;
            while ((temp = reader.readLine()) != null) {
                buffer.append(temp);
                buffer.append("\n");
            }//
            logger.info("***************登录配置请求结果**************:"  + buffer.toString().contains("{\"validateMessagesShowId\":\"_validatorMessage\",\"status\":true,\"httpstatus\":200,\"data\""));
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("登录配置异常 e:"+ e);
        }
    }
}
